iT邦幫忙

2025 iThome 鐵人賽

DAY 23
1
Odoo

Odoo × 生成式 AI:從零到一的企業自動化實戰系列 第 23

Day 23:企業級安全堡壘:資料保護與合規性指南

  • 分享至 

  • xImage
  •  

你將學到

  • 了解 GDPR 的「被遺忘權」與數據存取權,並在 Odoo 中實作合法刪除/匿名化流程。
  • 掌握資料遮罩與脫敏技術,包括 Odoo 內建的 obfuscate 工具和自訂 ORM 覆寫,保護客戶資料在客服聊天及合約記錄中的安全。

關鍵字

  • GDPR、被遺忘權、匿名化、資料遮罩、Access Groups、Record Rules

合約管理與客服對話的隱私挑戰

在 Odoo 18 的開發時程中,將 AI 聊天與合約管理模組結合,可以大幅提升客服效率與文件處理自動化。然而,企業不得忽視資料安全與隱私合規,尤其是 GDPR 等嚴格的法規。

今天我們以合約管理與客服對話的日常場景為出發點,分享如何在 Odoo 18 中落實合規、安全與匿名化的實務策略。

想像一家 SaaS 公司透過 Odoo 管理客戶合約,並利用內建的客服模組(Live Chat 或 Helpdesk)與客戶溝通。客服聊天中可能出現「客戶姓名、電話、公司名稱或合約條款」等敏感資訊,合約管理模組還存有簽約人身分證號與稅號。

當公司希望導入 AI 聊天機器人協助回答合約問題或生成總結時,若直接將聊天與合約內容送到外部的 LLM,就會暴露隱私風險;同時,客戶依 GDPR 具有要求刪除資料或查詢個人資訊的權利。因此,企業必須搭建「安全堡壘」,在滿足合規的前提下建置 AI 功能。


GDPR 合規策略:在 Odoo 上實踐被遺忘權

GDPR 的第 17 條「被遺忘權」允許資料主體要求刪除個人資料。

Odoo 官方說明指出,若聯絡人並未被任何業務文件(如發票、合約)引用,可直接刪除;若仍被引用,系統會阻止刪除並建議進行匿名化。

要在 Odoo 實踐此流程,可分為兩步:允許客戶提交刪除申請,及在資料保留需要時進行匿名化。

刪除申請與日誌

企業可在前台新增「刪除/匿名化請求」表單,客戶填寫後生成 gdpr.request 紀錄,供資料保護主管審核。經審核通過後,對於沒有關聯記錄的聯絡人調用 unlink() 直接刪除;若有關聯的發票或合約,則調用 anonymization 模組。

以下是一個簡化的 Odoo 模組範例:

# models/gdpr_request.py
from odoo import models, fields, api, _

class GdprRequest(models.Model):
    _name = 'gdpr.request'
    _description = 'GDPR Deletion or Anonymization Request'

    partner_id = fields.Many2one('res.partner', required=True)
    state = fields.Selection([('draft','Draft'),('approved','Approved'),('done','Processed')], default='draft')
    request_type = fields.Selection([('delete','Delete'),('anonymize','Anonymize')], required=True)

    def action_process(self):
        for req in self:
            if req.state != 'approved':
                continue
            partner = req.partner_id
            # 如果沒有任何業務文件引用,刪除
            if not partner.sale_order_ids and not partner.invoice_ids:
                partner.unlink()
            else:
                # 匿名化:保留與公司關聯,但清空個人資料
                partner.name = _('Anonymized Partner')
                partner.email = False
                partner.phone = False
                partner.street = False
                partner.vat = False
                # 其他欄位依需求清空
            req.state = 'done'

這段展示了如何依資料狀態決定刪除或匿名化,符合 Odoo 官方建議。

💡 Gary’s Pro Tip|紀錄審計日誌
實施 GDPR 流程前,先將所有刪除/匿名化請求動作記錄到安全的審計日誌,便於未來審核與合規查驗。此外,可建立自動通知機制,讓合約負責人與 IT 安全人員在資料被刪除前取得雙重確認。


資料遮罩與脫敏:保護聊天與合約內容

除了合法刪除/匿名化,運營中更需要對敏感資料進行即時遮蔽。例如客服系統中的問題包含姓名或公司名稱,但 AI 模型僅需要上下文語意即可生成回答。Odoo 提供兩種技術路徑:

1 . 使用 obfuscate 命令產生脫敏資料庫

Odoo 16 起內建 obfuscate 工具,可將資料庫中的姓名、電話、郵件等以隨機值替換,生成脫敏版本。這通常用於開發或測試環境,以便分享數據給第三方而不暴露個資。指令例子:

python3 odoo-bin obfuscate -d production_db --password=admin --obfuscate-dest=test_db

這會讀取 production_db,隨機化敏感欄位後儲存為 test_db

2 . 覆寫 ORM read 方法或使用 Compute 字段進行遮罩

若要在生產環境中即時遮蔽資料,可在模型中覆寫 read(),針對不具查看權限的使用者將敏感欄位覆蓋為星號或部分遮掩。例如在 helpdesk.ticket 中顯示客戶電話時,只有客服主管組可以看到完整號碼,其他人看到被遮蔽的資料。

from odoo import models, api, SUPERUSER_ID

class HelpdeskTicket(models.Model):
    _inherit = 'helpdesk.ticket'

    @api.model
    def read(self, fields=None, load='_classic_read'):
        records = super().read(fields=fields, load=load)
        # 檢查當前使用者是否屬於客服主管組
        is_manager = self.env.user.has_group('helpdesk.group_helpdesk_manager')
        mask_fields = ['partner_phone', 'partner_name']
        if not is_manager:
            for record in records:
                for f in mask_fields:
                    if f in record and record[f]:
                        value = record[f]
                        record[f] = value[0] + '*'*(len(value)-1)
        return records

這段程式碼呼叫父類的 read() 取得資料,然後判斷當前使用者是否隸屬 helpdesk_manager 群組。若沒有權限,便將電話號碼與姓名變成第一個字後加上星號遮蔽。另一種做法是在 res.partner 模型新增計算欄位 masked_phone,透過 @api.depends 根據使用者權限動態產生遮蔽值,並在視圖中顯示這個計算欄位。無論哪種方式,都需搭配正確的 Record Rule 以及 field-level groups 屬性限制欄位存取權。

💡 Gary’s Pro Tip|有效地處理資料庫脫敏
在覆寫 read() 時應注意效能,避免對所有紀錄逐一處理造成延遲。可以透過限制只在需要遮罩的模型與欄位中執行,並盡量在 SQL 層透過 select 子句選取必要欄位。另外,記得為被遮罩欄位設置 groups 屬性,以避免不應顯示的欄位被直接讀取。


私有 LLM 部署:保障企業資料不外洩

許多企業導入 AI 時會直接使用雲端服務,但這會將客戶資料傳送至第三方平台,增加合規風險。在建置 Retrieval‑Augmented Generation (RAG) 應用時,如果選擇本地部署,就能將敏感文件儲存於向量資料庫,並在自己的伺服器上運行 LLM,避免資料流出。

在 Odoo 整合 AI 的私有部署架構:

private-llm-deploy

在此架構中:

  1. Odoo 模組 先將聊天內容或合約摘要傳送給 FastAPI 服務。傳送前會利用前述覆寫函式將姓名、電話等匿名化,只保留必要的上下文。
  2. FastAPI 將匿名化的查詢向量化,並在本機的向量資料庫中搜尋相關文件。
  3. 本地 LLM 引擎 (如 Gemma、Qwen、DeepSeek)產生基於上下文的回覆,而整個流程在企業內網內完成。

💡 Gary’s Pro Tip|模型大小與硬體需求
選擇 LLM 時應考慮模型大小與硬體需求,建議先在開發環境測試 vLLM 或 Ollama 等 LLM 服務引擎,確認回覆品質與延遲後再部署於正式環境。此外,定期更新向量資料庫以納入最新合約與文件,確保回答的正確性。


權限設定:Access Groups 與 Record Rules

在 AI 整合方案中,誰可以看到什麼資料同樣關鍵。Odoo 透過 Access GroupsRecord Rules 實現細粒度控制。

每個模型都有 ir.model.access 記錄,定義了對應群組的讀寫刪除權;Record Rules 則使用 domain 條件限制使用者對個別記錄的操作範圍。

若需要更進一步的欄位級別控制,可以在欄位定義上加上 groups 屬性,使非指定群組的使用者無法看到該欄位。

設定專屬 AI 回覆群組

舉例來說,只有客服主管和法務部門可以查看 AI 回覆中可能包含合約摘要的敏感信息;其他客服只能看到處理過的摘要。

可在安全設定中建立群組 group_ai_full_access,並在 res.config.settings 中新增 boolean 欄位來打開或關閉完整回覆權限。

以下是一個 Record Rule 範例,限制只有群組成員可讀取 ai.message 模型的完整內容:

<!-- security/ir.model.access.csv -->
ai_security,ai.message,model_ai_message,group_ai_full_access,1,1,0,0

<!-- security/ai_security.xml -->
<record id="ai_message_rule" model="ir.rule">
    <field name="name">AI Message Access</field>
    <field name="model_id" ref="model_ai_message"/>
    <field name="groups" eval="[(4, ref('group_ai_full_access'))]"/>
    <field name="domain_force">[(1,'=',1)]</field>
</record>

這裡使用 ir.model.access 定義群組的讀權,ir.ruledomain_force 始終為真,使得只有 group_ai_full_access 會員可以讀取 ai.message

若要限制欄位,例如 ai.messageraw_content,可在欄位定義加入 groups="module_name.group_ai_full_access"

💡 Gary’s Pro Tip|權限策略
在設計權限策略時,建議遵循「最小權限原則」:預設不授權,必要時細緻授權。對於 AI 系統生成的數據,可以考慮在複雜的場景中建立兩個模型:一個存儲處理後的安全內容給一般使用者閱讀,另一個存儲完整內容供主管群組審核。這樣既符合安全要求,又不影響日常工作效率。


今日結語

結合 Odoo 與 AI 可以帶來巨大的生產力提升,但在企業級環境中安全與隱私不能妥協

今天介紹了從 GDPR 合規到資料遮罩、匿名化、私有 LLM 部署以及權限控制的一系列實務策略。

中大型企業在導入 AI 方案前,制定嚴格的安全審查流程,建立刪除/匿名化的標準作業程序,並在測試環境中模擬攻擊情境,確保每個環節都能保護客戶的權利與企業的信譽。

隨著 AI 技術快速進步,唯有持續關注法規與最佳實踐,才能打造真正穩固的「企業級安全堡壘」。


上一篇
Day 22:從會計到人資的智慧化升級:AI 在各模組的應用
下一篇
Day 24:效能與成本雙重優化:大模型應用的經濟學
系列文
Odoo × 生成式 AI:從零到一的企業自動化實戰24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言